package com.xcity.game.rank.impl;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Player;
import com.xcity.db.entity.Ranking;
import com.xcity.game.account.AccountChannel;
import com.xcity.game.combat.CombatUtils;
import com.xcity.game.event.GameEvents;
import com.xcity.game.formation.Formation;
import com.xcity.game.rank.BaseRankingList;
import com.xcity.game.rank.RankingList;

import naga.x.event.Event;
import naga.x.util.CollectionProcedure;

/**
 * QQ好友战斗力排行榜<br/>
 * @see AccountChannel#QQ_WANBA
 * @see AccountChannel#QQ
 * @author yang.li
 *
 */
public class QQFriendsRankingList implements RankingList {
	
	private byte type;
	private int capacity;
	private Comparator<Ranking> comparator;
	// 存储所有在线玩家的QQ好友排行列表
	private Map<Long, Entry> entryLookup;
	
	public QQFriendsRankingList(int type, int capacity, Comparator<Ranking> comparator) {
		this.type = (byte) type;
		this.capacity = capacity;
		this.comparator = comparator;
		this.entryLookup = new ConcurrentHashMap<>(32);
	}

	@Override
	public int[] getEventTypes() {
		return new int[] {
//				GameEvents.EVENT_PLAYER_LOADED,
//				GameEvents.EVENT_PLAYER_LOGOUT,
				GameEvents.EVENT_COMBAT_POWER_CHANGED,
				GameEvents.EVENT_EMPLOYEE_COMBAT_POWER_CHANGED,
				GameEvents.EVENT_FORMATION_CHANGED
		};
	}

	@Override
	public void handleEvent(Event event) {
		switch (event.getType()) {
//			case GameEvents.EVENT_PLAYER_LOADED:
//				playerLoaded(event.getParameter(0));
//				break;
//			case GameEvents.EVENT_PLAYER_LOGOUT:
//				playerLogout(event.getParameter(0));
//				break;
			case GameEvents.EVENT_COMBAT_POWER_CHANGED:
				fireCombatPowerChanged((Player) event.getParameter(0));
				break;
			case GameEvents.EVENT_EMPLOYEE_COMBAT_POWER_CHANGED:
				fireCombatPowerChanged((Employee) event.getParameter(0));
				break;
			case GameEvents.EVENT_FORMATION_CHANGED:
				fireCombatPowerChanged((Player) event.getParameter(0));
				break;
		}
	}

	@Override
	public void init() {
		// DO NOTHING
	}

	@Override
	public byte getType() {
		return type;
	}

	@Override
	public int getCapacity() {
		return capacity;
	}

	@Override
	public int size() {
		throw new UnsupportedOperationException();
	}

	@Override
	public void add(Ranking entry) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void addAll(Collection<Ranking> entries) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void remove(Player player) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void remove(long key) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void clearAsync() {
		throw new UnsupportedOperationException();
	}
	
	@Override
	public void clear() {
		throw new UnsupportedOperationException();
	}

	@Override
	public void save() {
//		throw new UnsupportedOperationException();
	}

	@Override
	public List<Ranking> getEntries() {
		throw new UnsupportedOperationException();
	}

	@Override
	public List<Ranking> getEntries(Player player) {
		Entry e = entryLookup.get(player.getId());
		return e != null ? e.getEntries() : null;
	}

	@Override
	public Ranking getEntry(int index) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Ranking findEntry(Player player) {
//		throw new UnsupportedOperationException();
		return findEntry(player.getId());
	}

	@Override
	public Ranking findEntry(long key) {
//		throw new UnsupportedOperationException();
		Entry entry = entryLookup.get(key);
		return entry != null ? entry.findEntry(key) : null;
	}

	@Override
	public boolean swap(Player player1, Player player2) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Ranking setDirty(Player player, long newValue) {
		AccountChannel ac = player.getAccount().getChannel();
		Ranking last = null;
		if (ac == AccountChannel.QQ_WANBA || ac == AccountChannel.QQ) {
			Entry entry = entryLookup.get(player.getId());
			if (entry != null) {
				// 更新player每个好友的好友排行榜
				List<Ranking> friends = entry.getEntries();
				for (int i = friends.size() - 1; i >= 0; i--) {
					last = friends.get(i);
					Entry e = entryLookup.get(last.getPlayerId());
					if (e != null) {
						e.setDirty(player, newValue);
					}
				}
				// 更新player自己的好友排行榜
				last = entry.setDirty(player, newValue);
			}
		}
		return last;
	}

	@Override
	public void doSort() {
		Collection<Entry> vals = entryLookup.values();
		for (Entry e : vals) {
			e.doSort();
		}
	}
	
	@Override
	public void forEach(CollectionProcedure<Ranking> procedure) {
		throw new UnsupportedOperationException("can't foreach the qq friends ranking list");
	}

	public void firePlayerLoaded(Player player, List<Player> friends) {
//		List<Player> friends = PlatformApi.getQQFriends(player);
//		if (friends == null || friends.isEmpty()) {
//			return;
//		}
		Entry e = new Entry(type, capacity >= friends.size() ? capacity : friends.size(), comparator);
		boolean excludeSelf = true;
		for (Player friend : friends) {
			int val = CombatUtils.getCombatPower(friend, friend.getFormations().get(Formation.TYPE_NORMAL).getUnits());
			Ranking entry = new Ranking(friend, type, val);
			e.add(entry);
			if (friend.getId() == player.getId()) {
				excludeSelf = false;
			}
		}
		if (excludeSelf) {
			// 好友列表没有自己
			int val = CombatUtils.getCombatPower(player, player.getFormations().get(Formation.TYPE_NORMAL).getUnits());
			e.add(new Ranking(player, type, val));
		}
		e.doSort();
		entryLookup.put(player.getId(), e);
	}
	
	public void firePlayerLogout(Player player) {
//		AccountChannel ac = player.getAccount().getChannel();
//		if (ac == AccountChannel.QQ_WANBA || ac == AccountChannel.QQ) {
			entryLookup.remove(player.getId());
//		}
	}
	
	private void fireCombatPowerChanged(Player player) {
		int val = CombatUtils.getCombatPower(player, player.getFormations().get(Formation.TYPE_NORMAL).getUnits());
		if (val > 0) {
			setDirty(player, val);
		}
	}
	
	private void fireCombatPowerChanged(Employee employee) {
		Player player = employee.getVm().getOwner();
		Formation f = player.getFormations().get(Formation.TYPE_NORMAL);
		if (f.contains(employee)) {
			// 普通阵型上的员工战斗力发生变化才更新
			fireCombatPowerChanged(player);
		}
	}
	
	public class Entry extends BaseRankingList {
		Entry(int type, int capacity, Comparator<Ranking> comparator) {
			super(type, capacity, comparator);
		}

		@Override
		public void init() {
			// DO NOTHING
		}
	}

}
